#include <iostream>
#include <string>
#include <string.h>
#include <strings.h>
#include <signal.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <sys/wait.h>

#include "Task.hpp"
#include "log.hpp"
#include "ThreadPool.hpp"

uint16_t defaultport = 8080;
static std::string defaultip = "0.0.0.0";
static const int gbacklog = 5;

namespace TcpServer
{
    class Server;

    class Context
    {
    public:
        Context(Server *server, int socket) : _server(server), _socket(socket)
        {
        }

        Server *_server;
        int _socket;
    };

    bool handlertext(int sock)
    {
        // 如何获取一个完整的数据字节流

        // read，把客户端的序号化的需求解析
        //std::string reqstr = read();

        //传入活动的序列化数据，以初始化req
        Request req;
        req.deserilize(reqstr);

        Response rep;
        // 执行任务
        calculate(req,rep);


        //活动序列化结果
        std::string rspstr;
        req.serilize(rspstr);

        // 序列化结果

        // write，把任务结果传输回去
        //write();
    }

    class Server
    {
    public:
        Server(const uint16_t &Serverport = defaultport, const std::string &Serverip = defaultip)
            : _Serverport(Serverport), _Serverip(Serverip), _sockfd(-1)
        {
        }
    

        void init()
        {
            // 穿件套接字，打开文件描述符
            _sockfd = socket(AF_INET, SOCK_STREAM, 0);
            if (_sockfd == -1)
            {
                // 打印错误日志，返回
                logmessage(FATAL, "socket failed");
                exit(1);
            }
            // 打印成功日志
            logmessage(SUCESS, "socket sucess");

            // 开始建立bind链接
            struct sockaddr_in address;
            bzero(&address, sizeof(address));
            address.sin_family = AF_INET;
            address.sin_port = htons(_Serverport);
            address.sin_addr.s_addr = INADDR_ANY;

            int n = bind(_sockfd, (struct sockaddr *)&address, sizeof(address));
            if (n == -1)
            {
                logmessage(FATAL, "bind failed");
                exit(2);
            }
            logmessage(SUCESS, "bind sucess");

            // 开始监听

            n = listen(_sockfd, gbacklog);
            if (n < 0)
            {
                logmessage(FATAL, "listen failed");
                exit(3);
            }
            logmessage(SUCESS, "listen sucess");
        }

        void start()
        {

            // 创建线程池
            //

            ThreadPool<Task>::getInstance();

            // 对SIGCHLD做了信号忽略处理时，也不会导致僵尸进程的现象
            // signal(SIGCHLD,SIG_IGN);
            // 正式开始工作
            //  1 . accpet建立接收客户端建立新链接
            while (1)
            {
                struct sockaddr_in address;
                bzero(&address, sizeof(address));
                socklen_t length = sizeof(address);
                int sock = accept(_sockfd, (struct sockaddr *)&address, &length);

                if (sock == -1)
                {
                    // logmessage("errno",getpid(),"notarget");
                    continue;
                }
                logmessage(SUCESS, "accept sucess");
                std::cout << "socketfd :" << sock << std::endl;

                // 建立链接成功，可以开始通信了
                //  int n = fork();

                // if(n == 0)
                // {
                //     //子进程一定要关闭从父进程基础来的listen套接字
                //     close(_sockfd);
                //     //孙子进程的资源会被操作系统自动回收，所以这样的执行方式才是对的
                //     //利用孤儿进程，即保证了多个服务器的行动，又保证了进程pid的回收
                //     if(fork()>0) exit(-1);
                //     serverio(sock);
                //     close(sock);
                // }

                // 因为父进程是阻塞等待子进程的，所以这是一种脱裤子放屁的玩法
                // 要实现真正的多进程通信，要利用好孤儿进程

                // 爷爷进程直接一秒回收父进程
                // pid_t  n =  waitpid(n,nullptr,0);
                //  if(n == -1)
                //  {
                //      logmessage("fatal",getpid(),"waitpid failed");
                //  }
                //  logmessage("sucess",getpid(),"waitpid sucess");

                // 现在开始实现多进程版本的tcp通讯

                // pthread_t tid;
                // Context* ctx = new Context(this,sock);
                // pthread_create(&tid,nullptr,provideServer,(void *)ctx);
                // 线程可不敢乱关文件描述符，因为是公用一套的

                // 到这里了,穿件一个任务push进入进程
                Task t(sock, handlertext);
                ThreadPool<Task>::getInstance()->push(t);
                ThreadPool<Task>::getInstance()->run();
            }
        }

        //    static void* provideServer(void * arvg)
        //    {
        //         pthread_detach(pthread_self());
        //         Context* ctx = static_cast<Context*>(arvg);
        //         //执行服务
        //         // ctx->_server->serverio(ctx->_socket);
        //         serverio(ctx->_socket);
        //         //执行完成后，释放文件描述符,并且释放被new出来了的 ctx
        //         close(ctx->_socket);
        //         delete ctx;
        //    }

    private:
        std::string _Serverip;
        uint16_t _Serverport;
        int _sockfd;
    };
}